/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package util;

/**
 *
 * @author Toshiba
 */
public class CLista {
   private CNodo primerNodo;
   private CNodo ultimoNodo;
   private CNodo actual=primerNodo;
   private String nombre;  
   // nombre es una cadena tal como "lista" usada en impresion

   // construye una  Lista vacía con un nombre
   public CLista( String cadena )
   {
      nombre = cadena;
      primerNodo = ultimoNodo = null;
   }

   // construye una Lista vacía con el nombre "lista"
   public CLista() 
   { 
      this( "lista" ); 
   }//operaciones sobre la lista
   public void actualizaActual(Object dato)
   {
       actual.actualizaObjeto(dato);
   }
   public Object devuelvePrimero()
   {
       actual=primerNodo;
       return primerNodo.obtenerObjeto();
   }
   public Object devuelveUltimo()
   {
       actual=ultimoNodo;
       return actual.obtenerObjeto();
   }
   public Object devuelveActual()
   {
       return actual.obtenerObjeto();
   }
   public Object devuleveSiguiente()
   {
       if(actual.nodoProximo!=null)
       {
           actual=actual.nodoProximo;
           return actual.obtenerObjeto();
       }
        else
           return null;
   }
   public Object devuelveAnterior()
   {
       if(actual.nodoAnterior!=null)
       {
           actual=actual.nodoAnterior;
           return actual.obtenerObjeto();
       }
       else
           return null;
   }
   // Inserta un Object delante de la Lista. Si la Lista esta vacía, 
   // primerNodo y ultimoNodo se refieren al mismo objeto.
   // De otra manera, primerNodo se refiere al nuevo nodo.
   public void insertarDelante( Object elementoAInsertar )
   {
      if ( estaVacio() )
         primerNodo = ultimoNodo = new CNodo( elementoAInsertar );

      else {
         CNodo desplazado = primerNodo;	
         primerNodo = new CNodo( elementoAInsertar,desplazado,null );
         desplazado.nodoAnterior=primerNodo;
      }
   }

   // Inserta un Object al final de una Lista. Sila Lista esta vacía,
   // primerNodo and ultimoNodo se refieren al mismo Objecto.
   // De otra manera, proximoNodo del ultimoNodo se refers al nuevo nodo.
   public void insertarDetras( Object elementoAInsertar )
   {
      if ( estaVacio() )
         primerNodo = ultimoNodo = new CNodo( elementoAInsertar );

      else {
         CNodo desplazado = ultimoNodo;
         ultimoNodo = new CNodo( elementoAInsertar,null,desplazado ); 
         desplazado.nodoProximo = ultimoNodo;
      }
   }

   // remueve el primer nodo de la Lista
   public synchronized Object removerDeDelante() throws ExcepcionListaVacia
   {
      Object elementoARemover = null;
      // lanza una excepción si la Lista esta vacía
      if ( estaVacio() )
         throw new ExcepcionListaVacia( nombre );

      // recupera el dato a ser removido
      elementoARemover = primerNodo.dato;  

      // reinicializa las referencias al primerNodo and ultimoNodo
      if ( primerNodo == ultimoNodo )
         primerNodo = ultimoNodo = null;

      else
      {
         primerNodo = primerNodo.nodoProximo;
         primerNodo.nodoAnterior = null;
         actual=primerNodo;

      }

      // devuelve el dato del nodo removido
      return actual.obtenerObjeto();  
   }

   // Remueve el último nodo de la Lista
   public synchronized Object removerDeDetras()
      throws ExcepcionListaVacia
   {
      Object elementoARemover = null;
      
      // lanza una excepción si la Lista esta vacía
      if ( estaVacio() )
         throw new ExcepcionListaVacia( nombre );

      // recupera el dato del que esta siendo removido
      elementoARemover = ultimoNodo.dato;  

      // reinicializa las referencias del primerNodo and ultimoNodo
      if ( primerNodo == ultimoNodo )
         primerNodo = ultimoNodo = null;

      else {
         
         ultimoNodo = ultimoNodo.nodoAnterior;
         ultimoNodo.nodoProximo = null;
         actual=ultimoNodo;
      }

      // devuelve el dato del nodo removido
      return actual.obtenerObjeto();
   }
   public synchronized Object eliminaActual()
   {
       actual.nodoAnterior.nodoProximo=actual.nodoProximo;
       actual.nodoProximo.nodoAnterior=actual.nodoAnterior;
       actual=actual.nodoAnterior;
       return actual.obtenerObjeto();
   }
   public synchronized void vaciar()
   {
       primerNodo=actual=ultimoNodo=null;
   }
   // retorna true si la Lista esta vacía
   public synchronized boolean estaVacio()
   { 
      return primerNodo == null; 
   }

   // salida de los contenidos de Lista del primero al último
   public synchronized void imprimir()
   {
      if ( estaVacio() ) {
         System.out.println( "Vacio " + nombre );
         return;
      }

      System.out.print( "La lista " + nombre + " es: " );

      CNodo actual = primerNodo;

      // mientras no es el final de la lista, se muestra
      // el dato del nodo actual
      while ( actual != null ) {
         System.out.print( actual.dato.toString() + " " );
         actual = actual.nodoProximo;
      }

      System.out.println( "\n" );
   }
   
   public synchronized void imprimirDesdeUltimo()
   {
      if ( estaVacio() ) {
         System.out.println( "Vacio " + nombre );
         return;
      }

      System.out.print( "La lista " + nombre + " es: " );

      CNodo actual = ultimoNodo;

      // mientras no es el final de la lista, se muestra
      // el dato del nodo actual
      while ( actual != null ) {
         System.out.print( actual.dato.toString() + " " );
         actual = actual.nodoAnterior;
      }

      System.out.println( "\n" );
   }   
 
}
